linkhighlighter.js

Tiny native javascript library to highlight current URI link.

Installation

npm i --save linkhighlighter

Usage

Direct include

Include script into your project and execute code right after DOM loaded.

<!-- ... -->
<script src="/static/assets/vendor/unsektor/linkhighlighter.js"></script>
<script>
window.addEventListener('DOMContentLoaded', function (e) {
    linkhighlighter.highlight();
});
</script>
</body>
<!-- ... -->

Include in frontend application

// AMD
define(['linkhighlighter'], function (linkhighlighter) {
  linkhighlighter.highlight();
})

// ES6 / ES2015 module
import linkhighlighter from 'linkhighlighter'

// CommonJS
var linkhighlighter = require('unsektor/linkhighlighter');

// Property of window object
window.linkhighlighter.highlight();
// ... or simply
linkhighlighter.highlight();

Notice: this code assumes that DOM is loaded.

Markup

Markup defines just only 3 custom HTML5 attributes.

1. data-lh attribute

data-lh attribute defines element to be highlighted.

Example 1:

Code without linkhighlighter markup (before):

<!-- ... -->
<header>
    <nav class="header-navigation">
        <a class="header-navigation__item" href="/">Main</a>
        <a class="header-navigation__item" href="/blog/">Blog</a>
        <a class="header-navigation__item" href="/news/">News</a>
        <a class="header-navigation__item" href="/contacts">Contacts</a>
    </nav>
</header>
<!-- ... -->

Code within linkhighlighter markup (after):

<!-- ... -->
<header>
    <nav class="header-navigation">
        <a data-lh class="header-navigation__item" href="/">Main</a>
        <a data-lh class="header-navigation__item" href="/blog/">Blog</a>
        <a data-lh class="header-navigation__item" href="/news/">News</a>
        <a data-lh class="header-navigation__item" href="/contacts">Contacts</a>
    </nav>
</header>
<!-- ... -->

It's enough to highlight current URI link elements.

data-lh values (options)

By default script highlights elements with data-lh attribute comparing element uri with current uri. There few options to extend functionality.

Option Compare method Description
match-uri (default) Strict equality of link URI to current URI.
Won't match any other url.
match-domain Strict equality of link host to current host Global navigation item
match-partial RegExp test Match parent directories to current URI

Example 2:

Code without linkhighlighter markup (before):

<!-- ... -->
<header>
    <nav class="header-navigation">
        <a class="header-navigation__item" href="//news.example.tld">News</a>
        <a class="header-navigation__item" href="//blog.example.tld">Blog</a>
        <a class="header-navigation__item" href="//www.example.tld">Main</a>
        <a class="header-navigation__item" href="//www.example.tld/contacts">Contacts</a>
    </nav>
</header>
<!-- ... -->

Code within linkhighlighter markup (after):

<!-- ... -->
<header>
    <nav class="header-navigation">
        <a data-lh="match-domain" class="header-navigation__item" href="//news.example.tld">News</a>
        <a data-lh="match-domain" class="header-navigation__item" href="//blog.example.tld">Blog</a>
        <a data-lh class="header-navigation__item" href="//www.example.tld">Main</a>
        <a data-lh class="header-navigation__item" href="//www.example.tld/contacts">Contacts</a>
    </nav>
</header>
<!-- ... -->

2. data-lh-scope (optional attribute)

data-lh-scope attribute applies to element to define scope that contains anchor (<a>) elements to be highlighted. It's usefull to segregate few link blocks (eg. navigation blocks). (See data-lh-class below for more details).

Scope element definition example:

<!-- ... -->
<header>
    <nav data-lh-scope>
        <!-- anchor elements to be highlighted -->
    </nav>
</header>
<!-- ... -->

Note: if at least one scope was not defined, document root element (<html>) will be used as the only scope.

3. data-lh-class (optional attribute)

data-lh-class attribute defines scope classname for highlighted anchor element. This attribute applies only for scope element (DOM element that contains data-lh-scope attribute). It's useful to define specific highlighted element class name in scope.

g-lh-active is default class name to highlight link element (if data-lh-class for scope was not defined).

This feature provides compatibility with BEM methodology.

Example when using data-lh-class is useful:

// SCSS code
.header-navigation {
    &__item {
        // Case 1. (without default class name definition for scope)
        // You have to define styles for default class name selector.
        // In BEM using case it's a dirty hack.
        &.g-lh-active { 
            // ...
        }

        // Case 2. (BEM ok)
        &_active {
            // ...
        }
    }
}

Result CSS code.

/* CSS Code*/

/* Case 1 result */ 
.header-navigation__item.g-lh-active {/* ... */}

/* Case 2 result */
.header-navigation__item_active {/* ... */}

Scope class name definition example:

<!-- ... -->
<header>
    <nav data-lh-scope data-lh-class="header-navigation__item_active">
        <!-- anchor elements to be highlighted -->
    </nav>
</header>
<!-- ... -->

Final example code:

<!-- ... -->
<header>
    <nav data-lh-scope data-lh-class="header-navigation__item_active" class="header-navigation">
        <a data-lh="match-domain" class="header-navigation__item" href="//news.example.tld">News</a>
        <a data-lh="match-domain" class="header-navigation__item" href="//blog.example.tld">Blog</a>
        <a data-lh class="header-navigation__item" href="//www.example.tld">Main</a>
        <a data-lh class="header-navigation__item" href="//www.example.tld/contacts">Contacts</a>
    </nav>
</header>
<!-- ... -->
<!-- Nested menu example -->
<!-- this markup allow to highlight nested categories for some entity (eg. blog article) -->
<ul class="list" data-lh-scope data-lh-class="list__link_active" >
    <li class="list__item">
        <a data-lh="match-partial" class="list__link" href="/*nix/">*NIX</a>
        <ul class="list">
            <li class="list__item"><a data-lh="match-partial" class="list__link" href="/*nix/os-x/">OS X</a></li>
            <li class="list__item"><a data-lh="match-partial" class="list__link" href="/*nix/linux/">Linux</a></li>
        </ul>
    </li>
    <li>
        <a data-lh="match-partial" class="list__link" href="/backend-development/">Backend development</a>
        <ul class="list">
            <li class="list__item"><a data-lh="match-partial" class="list__link" href="/backend-development/node.js/">Node.js</a></li>
            <li class="list__item"><a data-lh="match-partial" class="list__link" href="/backend-development/php/">PHP</a></li>
            <li class="list__item"><a data-lh="match-partial" class="list__link" href="/backend-development/mysql/">MySQL</a></li>
            <li class="list__item"><a data-lh="match-partial" class="list__link" href="/backend-development/nosql/">NoSQL</a></li>
        </ul>
    </li>
</ul>
<!-- ... -->
<footer>
    <nav data-lh-scope data-lh-class="footer-navigation__item_active" class="footer-navigation">
        <a data-lh class="footer-navigation__item" href="//www.example.tld/api">API</a>
        <a data-lh class="footer-navigation__item" href="//www.example.tld/status">Service status</a>
        <a data-lh class="footer-navigation__item" href="//www.example.tld/about">About</a>
    </nav>
</footer>
<!-- ... -->

Notes & restrictions

  1. Currently, library does not watch DOM & URI changes, if your application manages it, it's simple to update state by simply calling main library method: highlight.
  2. script uses classList DOM API & HTML5 custom data attributes.
  3. script does not validate passed options.

Change Log

License